/* <pre>
 * Copyright (c) The Loose Coupling Team.
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 *</pre>
 */

package org.lc.eic.messaging.requestreply;

import javax.jms.JMSException;

import org.lc.eic.api.requestreply.exception.RequestProcessingException;
import org.lc.eic.core.pipesandfilters.impl.GZIPCompressDataFilter;
import org.lc.eic.core.pipesandfilters.impl.GZIPUncompressDataFilter;
import org.lc.eic.messageconstruct.jaxb.content.ContentMapper;
import org.lc.eic.messageconstruct.requestreply.jaxb.impl.JAXBReplySerializer;
import org.lc.eic.messageconstruct.requestreply.jaxb.impl.JAXBRequestSerializer;
import org.lc.eic.messaging.assembly.AsyncRequestDispatcher;
import org.lc.eic.messaging.assembly.DeserializeReplyFilter;
import org.lc.eic.messaging.assembly.EnvelopeWrapRequestDispatcher;
import org.lc.eic.messaging.assembly.ReceiveDataPipe;
import org.lc.eic.messaging.assembly.RequestSynchronizer;
import org.lc.eic.messaging.assembly.SendDataPipe;
import org.lc.eic.messaging.assembly.SerializeRequestFilter;
import org.lc.eic.messagingsystem.activemq.ActiveMQMessagingSystem;
import org.lc.eic.messagingsystem.exception.RegistrationException;
import org.lc.eic.messagingsystem.exception.StartMessagingException;



/**
 *  TODO: Add type comment here!!
 *	@author <a href="mailto:p.lycke@googlemail.com">PaLy</a>
 *
 * 
 */
public class RequestDispatcher<I, O> implements
		org.lc.eic.api.requestreply.sync.RequestDispatcher<I, O> {
	
	
	private EnvelopeWrapRequestDispatcher<I, O> envelopeRequestDispatcher = new EnvelopeWrapRequestDispatcher<I, O>();
	
	public RequestDispatcher(String activeMQUrl, String sendQueue, String receiveQueue, ContentMapper contentMapper){
		//Create components		
		RequestSynchronizer<I, O> requestSynchronizer = new RequestSynchronizer<I, O>();
		AsyncRequestDispatcher<I, O> asyncRequestDispatcher = new AsyncRequestDispatcher<I, O>();
		
		SerializeRequestFilter<I> serializeRequestFilter = new SerializeRequestFilter<I>();
		JAXBRequestSerializer<I> jaxbRequestSerializer = new JAXBRequestSerializer<I>();
		
		DeserializeReplyFilter<O> deserializeReplyFilter = new DeserializeReplyFilter<O>();
		JAXBReplySerializer<O> jaxbReplySerializer = new JAXBReplySerializer<O>();
		
		
		ActiveMQMessagingSystem activeMQMessagingSystem = null;
		try {
			activeMQMessagingSystem = new ActiveMQMessagingSystem(activeMQUrl);
		} catch (JMSException e) {
			throw new RuntimeException(e);
		}
		
		
		
		SendDataPipe sendRequestPipe = new SendDataPipe();
		ReceiveDataPipe receiveReplyPipe = new ReceiveDataPipe();
		
		//Assemble them
		envelopeRequestDispatcher.setRequestDispatcher(requestSynchronizer);
		requestSynchronizer.setAsyncRequestDispatcher(asyncRequestDispatcher);
		
		asyncRequestDispatcher.setRequestPipe(serializeRequestFilter);
		deserializeReplyFilter.setOutboundPipe( asyncRequestDispatcher.getReplyPipe() );
		
		serializeRequestFilter.setRequestSerializer(jaxbRequestSerializer);
		deserializeReplyFilter.setReplySerializer(jaxbReplySerializer);
		
		jaxbRequestSerializer.setContentMapper(contentMapper);
		jaxbReplySerializer.setContentMapper(contentMapper);
		
		
		serializeRequestFilter.setOutboundPipe(new GZIPCompressDataFilter(sendRequestPipe));		
		receiveReplyPipe.setInboundPipe(new GZIPUncompressDataFilter(deserializeReplyFilter));
		
		
		try {
			activeMQMessagingSystem.registerOutboundEndpoint(sendRequestPipe, sendQueue);
			activeMQMessagingSystem.registerInboundEndpoint(receiveReplyPipe, receiveQueue);
		} catch (RegistrationException e) {
			throw new RuntimeException(e);
		}
		
		try {
			activeMQMessagingSystem.startMessaging();
		} catch (StartMessagingException e) {
			throw new RuntimeException(e);
		}
		
	}

	/**
	 * @see org.lc.eic.api.requestreply.sync.RequestDispatcher#request(java.lang.Object)
	 */
	@Override
	public O request(I request) throws RequestProcessingException {
		return envelopeRequestDispatcher.request(request);
	}

}
